package git.soulbgm.config;

import git.soulbgm.common.redis.JdkSerializationRedisSerializer;
import git.soulbgm.utils.ClassUtil;
import git.soulbgm.utils.LogUtil;
import org.crazycake.shiro.IRedisManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSentinelManager;
import org.crazycake.shiro.RedisClusterManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.*;
import redis.clients.util.Pool;

import java.util.Set;

/**
 * @author SoulBGM
 * @version 1.0
 * @date 2019/10/17 9:35
 */
@Configuration
public class RedisConfig {

    private LogUtil log = new LogUtil(getClass());

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate template = new RedisTemplate();
        template.setConnectionFactory(factory);
        //序列化设置 ，这样计算是正常显示的数据，也能正常存储和获取
        template.setKeySerializer(new StringRedisSerializer());
        template.setValueSerializer(new JdkSerializationRedisSerializer());
        template.afterPropertiesSet();
        try {
            // 检查一下redis是否在线
            template.keys("name");
        } catch (Exception e) {
            if (e instanceof RedisConnectionFailureException) {
                log.error("Cannot get Jedis connection", e);
            }
            System.exit(-1);
        }
        return template;
    }

    /**
     * 配置shiro redisManager
     * 使用的是shiro-redis开源插件
     *
     * 从RedisConnectionFactory中取出PoolConfig和Pool赋值到各自的IRedisManager中
     * 这样可以是shiro使用的 jedis 连接池和 RedisTemplate 使用的连接池是同一个
     * 这样就可以和SpringBoot整合到一块 不管使用的是单机、哨兵还是集群都可以兼容 O(∩_∩)O
     */
    @Bean
    public IRedisManager redisManager(RedisConnectionFactory factory) throws NoSuchFieldException, IllegalAccessException {
        IRedisManager rm = null;
        if (!(factory instanceof JedisConnectionFactory)) {
            throw new RuntimeException("请选择Jedis");
        }
        JedisConnectionFactory jedisFactory = (JedisConnectionFactory) factory;
        JedisPoolConfig poolConfig = jedisFactory.getPoolConfig();
        Pool<Jedis> pool = ClassUtil.getFieldVal(jedisFactory, "pool");
        if (pool instanceof JedisPool) {
            // 单机模式
            RedisManager redisManager = new RedisManager();
            /*redisManager.setHost("127.0.0.1:6379");
            redisManager.setDatabase(0);
            redisManager.setPassword("");
            // 连接Redis服务器超时时间 单位毫秒
            redisManager.setTimeout(500);*/
            redisManager.setJedisPoolConfig(poolConfig);
            redisManager.setJedisPool((JedisPool) pool);
            rm = redisManager;
        } else if (pool instanceof JedisSentinelPool) {
            // 哨兵模式
            RedisSentinelManager redisSentinelManager = new RedisSentinelManager();
            /*redisSentinelManager.setHost("127.0.0.1:26379,127.0.0.1:26380,127.0.0.1:26381");
            redisSentinelManager.setPassword("");
            redisSentinelManager.setMasterName("mymaster");
            redisSentinelManager.setDatabase(0);
            // 连接Redis服务器超时时间 单位毫秒
            redisSentinelManager.setTimeout(2000);
            // 读取数据超时时间 单位毫秒
            redisSentinelManager.setSoTimeout(500);*/
            redisSentinelManager.setJedisPoolConfig(poolConfig);
            redisSentinelManager.setJedisPool((JedisSentinelPool) pool);
            rm = redisSentinelManager;
        } else {
            // 集群模式
            JedisCluster jedisCluster = ClassUtil.getFieldVal(jedisFactory, "cluster");
            RedisClusterManager redisClusterManager = new RedisClusterManager();
            /*redisClusterManager.setHost("127.0.0.1:7000,127.0.0.1:7001,127.0.0.1:7002");
            redisClusterManager.setDatabase(0);
            redisClusterManager.setPassword("");
            redisClusterManager.setTimeout(2000);
            redisClusterManager.setSoTimeout(500);
            redisClusterManager.setMaxAttempts(0);
            redisClusterManager.setCount(0);*/
            redisClusterManager.setJedisPoolConfig(poolConfig);
            redisClusterManager.setJedisCluster(jedisCluster);
            rm = redisClusterManager;
        }
        return rm;
    }

}
